package com.suep.data_analysis.service;

import com.suep.data_analysis.dto.*;
import com.suep.data_analysis.model.AgentSkills;
import com.suep.data_analysis.repository.AgentSkillsRepository;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * 伤害计算服务
 * 基于角色最终属性面板和技能信息计算伤害
 */
@Service
@AllArgsConstructor
public class DamageCalculationService {
    private final CharacterStatsCalculationService characterStatsCalculationService;
    private final AgentSkillsRepository agentSkillsRepository;
    private final Random random = new Random();

    /**
     * 计算技能伤害
     * 
     * @param userConfig 用户配置
     * @param request 伤害计算请求
     * @return 伤害计算结果
     */
    public DamageCalculationResultDto calculateDamage(UserConfigDetailDto userConfig, DamageCalculationRequestDto request) {
        // 获取角色最终属性面板
        CharacterStatsDto characterStats = characterStatsCalculationService.calculateFinalStats(userConfig);
        
        // 获取技能信息
        AgentSkills skill = agentSkillsRepository.findBySkillId(request.getSkillId());
        if (skill == null) {
            throw new IllegalArgumentException("技能不存在: " + request.getSkillId());
        }

        // 检查技能类型，排除核心技和闪避
        if ("核心技".equals(skill.getSkillType()) || "闪避".equals(skill.getSkillType())) {
            throw new IllegalArgumentException("该技能类型不支持伤害计算: " + skill.getSkillType());
        }

        // 检查技能是否有伤害倍率
        if (skill.getDamageMultiplier() == null || skill.getDamageMultiplier().doubleValue() <= 0) {
            throw new IllegalArgumentException("该技能没有伤害倍率，无法计算伤害");
        }

        // 创建结果对象
        DamageCalculationResultDto result = new DamageCalculationResultDto();
        result.setSkillId(request.getSkillId());
        result.setSkillName(skill.getSkillName());
        result.setSkillType(skill.getSkillType());
        result.setElementType(request.getElementType());
        result.setTargetType(request.getTargetType());
        result.setTargetLevel(request.getTargetLevel());
        result.setTargetDefense(request.getTargetDefense() != null ? request.getTargetDefense() : 0.0);
        result.setTargetResistance(request.getTargetResistance() != null ? request.getTargetResistance() : 0.0);

        // 创建计算过程对象
        DamageCalculationProcessDto process = new DamageCalculationProcessDto();
        List<String> steps = new ArrayList<>();

        // 1. 基础伤害计算（使用最终攻击力）
        double attackPower = characterStats.getFinalAtk();
        double skillMultiplier = skill.getDamageMultiplier().doubleValue() / 100.0; // 转换为小数（837.1% -> 8.371）
        double skillBaseDamage = attackPower * skillMultiplier;
        
        process.setAttackPower(attackPower);
        process.setSkillMultiplier(skillMultiplier);
        process.setSkillBaseDamage(skillBaseDamage);
        steps.add(String.format("基础伤害 = 最终攻击力(%.0f) × 技能倍率(%.2f) = %.0f", 
                attackPower, skillMultiplier, skillBaseDamage));

        // 2. 元素伤害加成（使用最终元素加成）
        double elementBonus = getElementBonus(characterStats, request.getElementType());
        double elementMultiplier = 1.0 + elementBonus; // 1 + 元素伤害加成
        
        process.setElementMultiplier(elementMultiplier);
        steps.add(String.format("元素倍率 = 1 + 元素伤害加成(%.2f%%) = %.2f", 
                elementBonus * 100, elementMultiplier));

        // 3. 暴击计算（使用最终暴击属性）
        double criticalRate = characterStats.getFinalCritRate();
        double criticalDamageRate = characterStats.getFinalCritDmg();
        boolean isCritical = request.getIsCritical() != null ? request.getIsCritical() : 
                           random.nextDouble() < (criticalRate / 100.0);
        
        // 修正暴击倍率计算方式
        double criticalMultiplier = isCritical ? (criticalDamageRate / 100.0) : 1.0;
        
        process.setCriticalMultiplier(criticalMultiplier);
        result.setCriticalRate(criticalRate);
        result.setCriticalDamageRate(criticalDamageRate);
        result.setIsCritical(isCritical);
        
        if (isCritical) {
            steps.add(String.format("暴击! 暴击倍率 = 暴击伤害(%.2f%%) = %.2f", 
                    criticalDamageRate, criticalMultiplier));
        } else {
            steps.add("未暴击，暴击倍率 = 1.0");
        }

        // 4. 失衡计算（如果有失衡倍率）
        boolean isImbalance = request.getIsImbalance() != null ? request.getIsImbalance() : false;
        double imbalanceMultiplier = 1.0;
        
        if (isImbalance && skill.getImbalanceMultiplier() != null && skill.getImbalanceMultiplier().doubleValue() > 0) {
            imbalanceMultiplier = skill.getImbalanceMultiplier().doubleValue() / 100.0;
            steps.add(String.format("失衡! 失衡倍率 = %.2f", imbalanceMultiplier));
        }
        
        process.setImbalanceMultiplier(imbalanceMultiplier);

        // 5. 防御力减免（使用最终穿透率）
        double penetrationRate = characterStats.getFinalPenetration();
        double targetDefense = request.getTargetDefense() != null ? request.getTargetDefense() : 0.0;
        double effectiveDefense = Math.max(0, targetDefense * (1.0 - penetrationRate));
        double defenseReduction = effectiveDefense / (effectiveDefense + 1000); // 假设防御力公式
        
        process.setDefenseReduction(defenseReduction);
        steps.add(String.format("防御力减免 = %.2f%% (穿透率: %.2f%%)", 
                defenseReduction * 100, penetrationRate * 100));

        // 6. 抗性减免
        double resistanceReduction = request.getTargetResistance() != null ? request.getTargetResistance() : 0.0;
        process.setResistanceReduction(resistanceReduction);
        if (resistanceReduction > 0) {
            steps.add(String.format("抗性减免 = %.2f%%", resistanceReduction * 100));
        }

        // 7. 最终伤害计算
        double finalDamage = skillBaseDamage * elementMultiplier * criticalMultiplier * 
                           imbalanceMultiplier * (1.0 - defenseReduction) * (1.0 - resistanceReduction);
        
        result.setBaseDamage(skillBaseDamage);
        result.setFinalDamage(finalDamage);
        result.setElementBonus(elementBonus * 100); // 转换为百分比格式存储
        result.setPenetrationEffect(penetrationRate);
        result.setResistanceEffect(resistanceReduction);

        // 计算暴击伤害
        if (isCritical) {
            result.setCriticalDamage(finalDamage);
        }

        // 计算失衡伤害
        if (isImbalance && imbalanceMultiplier > 1.0) {
            result.setImbalanceDamage(finalDamage);
        }

        steps.add(String.format("最终伤害 = %.0f × %.2f × %.2f × %.2f × %.2f × %.2f = %.0f",
                skillBaseDamage, elementMultiplier, criticalMultiplier, imbalanceMultiplier,
                1.0 - defenseReduction, 1.0 - resistanceReduction, finalDamage));

        process.setCalculationSteps(steps);
        result.setCalculationProcess(process);

        return result;
    }

    /**
     * 获取元素伤害加成（使用最终属性面板中的元素加成）
     */
    private double getElementBonus(CharacterStatsDto characterStats, String elementType) {
        if (elementType == null) return 0.0;
        
        switch (elementType.toLowerCase()) {
            case "物理":
                return characterStats.getPhysicalBonus();
            case "以太":
                return characterStats.getEtherBonus();
            case "火":
            case "火属性":
                return characterStats.getFireBonus();
            case "冰":
            case "冰属性":
                return characterStats.getIceBonus();
            case "电":
            case "电属性":
                return characterStats.getElectricBonus();
            default:
                return 0.0;
        }
    }

    /**
     * 批量计算多个技能伤害
     * 
     * @param userConfig 用户配置
     * @param skillIds 技能ID列表
     * @param elementType 元素类型
     * @param isCritical 是否暴击
     * @return 伤害计算结果列表
     */
    public List<DamageCalculationResultDto> calculateMultipleSkills(
            UserConfigDetailDto userConfig, 
            List<String> skillIds, 
            String elementType,
            Boolean isCritical
    ) {
        List<DamageCalculationResultDto> results = new ArrayList<>();
        for (String skillId : skillIds) {
            DamageCalculationRequestDto request = new DamageCalculationRequestDto();
            request.setSkillId(skillId);
            request.setElementType(elementType);
            request.setIsCritical(isCritical); // 支持null/true/false
            request.setTargetDefense(0.0); // 设置默认目标防御力
            request.setTargetResistance(0.0); // 设置默认目标抗性
            try {
                DamageCalculationResultDto result = calculateDamage(userConfig, request);
                results.add(result);
            } catch (Exception e) {
                // 记录错误但继续处理其他技能
                System.err.println("计算技能 " + skillId + " 伤害时出错: " + e.getMessage());
            }
        }
        return results;
    }

    /**
     * 计算技能伤害范围（考虑暴击概率）
     * 
     * @param userConfig 用户配置
     * @param request 伤害计算请求
     * @param iterations 模拟次数
     * @return 伤害范围统计
     */
    public DamageRangeResultDto calculateDamageRange(
            UserConfigDetailDto userConfig, 
            DamageCalculationRequestDto request, 
            int iterations) {
        
        List<Double> damages = new ArrayList<>();
        int criticalCount = 0;
        
        for (int i = 0; i < iterations; i++) {
            DamageCalculationRequestDto simRequest = new DamageCalculationRequestDto();
            simRequest.setSkillId(request.getSkillId());
            simRequest.setTargetType(request.getTargetType());
            simRequest.setTargetLevel(request.getTargetLevel());
            simRequest.setTargetDefense(request.getTargetDefense() != null ? request.getTargetDefense() : 0.0);
            simRequest.setTargetResistance(request.getTargetResistance() != null ? request.getTargetResistance() : 0.0);
            simRequest.setIsCritical(null); // 随机暴击
            simRequest.setIsImbalance(request.getIsImbalance());
            simRequest.setElementType(request.getElementType());
            
            try {
                DamageCalculationResultDto result = calculateDamage(userConfig, simRequest);
                damages.add(result.getFinalDamage());
                if (result.getIsCritical()) {
                    criticalCount++;
                }
            } catch (Exception e) {
                // 跳过错误的计算
                System.err.println("模拟计算第 " + (i+1) + " 次时出错: " + e.getMessage());
            }
        }
        
        // 计算统计信息
        double avgDamage = damages.stream().mapToDouble(Double::doubleValue).average().orElse(0.0);
        double minDamage = damages.stream().mapToDouble(Double::doubleValue).min().orElse(0.0);
        double maxDamage = damages.stream().mapToDouble(Double::doubleValue).max().orElse(0.0);
        double criticalRate = damages.isEmpty() ? 0.0 : (double) criticalCount / damages.size();
        
        DamageRangeResultDto rangeResult = new DamageRangeResultDto();
        rangeResult.setSkillId(request.getSkillId());
        rangeResult.setAverageDamage(avgDamage);
        rangeResult.setMinDamage(minDamage);
        rangeResult.setMaxDamage(maxDamage);
        rangeResult.setCriticalRate(criticalRate);
        rangeResult.setIterations(damages.size());
        rangeResult.setElementType(request.getElementType());
        
        return rangeResult;
    }

    /**
     * 获取角色的所有可计算伤害的技能
     * 
     * @param agentId 代理人ID
     * @return 可计算伤害的技能列表
     */
    public List<AgentSkills> getDamageSkills(String agentId) {
        List<AgentSkills> allSkills = agentSkillsRepository.selectAllByAgentId(agentId);
        List<AgentSkills> damageSkills = new ArrayList<>();
        
        for (AgentSkills skill : allSkills) {
            // 排除核心技和闪避
            if (!"核心技".equals(skill.getSkillType()) && !"闪避".equals(skill.getSkillType())) {
                // 检查是否有伤害倍率
                if (skill.getDamageMultiplier() != null && skill.getDamageMultiplier().doubleValue() > 0) {
                    damageSkills.add(skill);
                }
            }
        }
        
        return damageSkills;
    }
} 